﻿using Onshi.POS.Modelo.Entidades;
using Onshi.POS.AccesoDatos.Interfaces;
using Onshi.POS.AccesoDatos;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using Onshi.POS.Modelo.Entidades.Tipos;

namespace Onshi.POS.Repositorios
{
    public class RepositorioProveedores : RepositorioEntidad<Proveedor, Int32, IServicioDatosProveedores>
    {
        #region Constructores

        public RepositorioProveedores()
            : base()
        {
        }

        #endregion

        #region Atributos

        private RepositorioTiposIvas repositorioTiposIvas = new RepositorioTiposIvas();
        private RepositorioRubrosProveedores repositorioRubrosProveedores = new RepositorioRubrosProveedores();
        private RepositorioTiposTelefonos repositorioTiposTelefonos = new RepositorioTiposTelefonos();
        private RepositorioTiposDomicilios repositorioTiposDomicilios = new RepositorioTiposDomicilios();
        private RepositorioBarrios repositorioBarrios = new RepositorioBarrios();
        private RepositorioTiposFormasPagos repositorioTiposFormasPagos = new RepositorioTiposFormasPagos();
        private RepositorioListasPreciosCompras repositorioListasPreciosCompras = new RepositorioListasPreciosCompras();
        private RepositorioCamposPersonalizadosProveedores repositorioCamposPersonalizadosProveedores = new RepositorioCamposPersonalizadosProveedores();

        #endregion

        #region Metodos

        public override Proveedor DevolverPorId(Int32 id)
        {
            return DevolverPorId(id, false);
        }

        public Proveedor DevolverPorCodigo(String codigo)
        {
            return DevolverPorCodigo(codigo, false);
        }

        public List<Proveedor> DevolverTodos()
        {
            return DevolverTodos(false);
        }

        public Proveedor DevolverPorId(Int32 id, Boolean incluirImagen)
        {
            var proveedor = entidades.Where(x => x.Id == id).FirstOrDefault();
            if (proveedor == null)
                using (var ds = servicioDatos.Proveedores_DevolverPorId(id, incluirImagen))
                    if (ds.Tables[0].Rows.Count > 0)
                    {
                        proveedor = FilaAEntidad(ds.Tables[0].Rows[0]);
                        proveedor.TiposFormasPagos = TablaAListaTiposFormasPagos(ds.Tables[1]);
                        proveedor.Domicilios = TablaAListaDomicilios(ds.Tables[2]);
                        proveedor.Telefonos = TablaAListaTelefonos(ds.Tables[3]);
                        proveedor.CamposPersonalizados = TablaAListaCamposPersonalizados(ds.Tables[4]);
                        entidades.Add(proveedor);
                    }
            return proveedor;
        }

        public Proveedor DevolverPorCodigo(String codigo, Boolean incluirImagen)
        {
            var proveedor = entidades.Where(x => x.Codigo == codigo).FirstOrDefault();
            if (proveedor == null)
                using (var ds = servicioDatos.Proveedores_DevolverPorCodigo(codigo, incluirImagen))
                    if (ds.Tables[0].Rows.Count > 0)
                    {
                        proveedor = FilaAEntidad(ds.Tables[0].Rows[0]);
                        proveedor.TiposFormasPagos = TablaAListaTiposFormasPagos(ds.Tables[1]);
                        proveedor.Domicilios = TablaAListaDomicilios(ds.Tables[2]);
                        proveedor.Telefonos = TablaAListaTelefonos(ds.Tables[3]);
                        proveedor.CamposPersonalizados = TablaAListaCamposPersonalizados(ds.Tables[4]);
                        entidades.Add(proveedor);
                    }
            return proveedor;
        }

        public List<Proveedor> DevolverTodos(Boolean incluirImagen)
        {
            using (var ds = servicioDatos.Proveedores_DevolverTodos(incluirImagen))
            {
                entidades = TablaALista(ds.Tables[0]);
                foreach (var proveedor in entidades)
                {
                    var tiposFormasPagos = ds.Tables[1].AsEnumerable().Where(x => (Int32)x["IdProveedor"] == proveedor.Id).AsDataView().ToTable();
                    proveedor.TiposFormasPagos = TablaAListaTiposFormasPagos(tiposFormasPagos);
                    var domicilios = ds.Tables[2].AsEnumerable().Where(x => (Int32)x["IdProveedor"] == proveedor.Id).AsDataView().ToTable();
                    proveedor.Domicilios = TablaAListaDomicilios(domicilios);
                    var telefonos = ds.Tables[3].AsEnumerable().Where(x => (Int32)x["IdProveedor"] == proveedor.Id).AsDataView().ToTable();
                    proveedor.Telefonos = TablaAListaTelefonos(telefonos);
                    var camposPersonalizados = ds.Tables[4].AsEnumerable().Where(x => (Int32)x["IdProveedor"] == proveedor.Id).AsDataView().ToTable();
                    proveedor.CamposPersonalizados = TablaAListaCamposPersonalizados(camposPersonalizados);
                }
            }
            return entidades;
        }

        private List<TipoFormaPago> TablaAListaTiposFormasPagos(DataTable tabla)
        {
            var tiposFormasPagos = new List<TipoFormaPago>();
            foreach (DataRow item in tabla.Rows)
                tiposFormasPagos.Add(repositorioTiposFormasPagos.DevolverPorId((Byte)item["IdTipoFormaPago"]));
            return tiposFormasPagos;
        }

        private List<DomicilioProveedor> TablaAListaDomicilios(DataTable tabla)
        {
            var domicilios = new List<DomicilioProveedor>();
            foreach (DataRow fila in tabla.Rows)
                domicilios.Add(FilaADomicilio(fila));
            return domicilios;
        }

        private List<TelefonoProveedor> TablaAListaTelefonos(DataTable tabla)
        {
            var telefonos = new List<TelefonoProveedor>();
            foreach (DataRow fila in tabla.Rows)
                telefonos.Add(FilaATelefono(fila));
            return telefonos;
        }

        private List<ProveedorCampoPersonalizadoProveedor> TablaAListaCamposPersonalizados(DataTable tabla)
        {
            var camposPersonalizadosProveedores = repositorioCamposPersonalizadosProveedores.DevolverTodos();
            var proveedoresCamposPersonalizadosProveedores = new List<ProveedorCampoPersonalizadoProveedor>();
            foreach (DataRow fila in tabla.Rows)
                proveedoresCamposPersonalizadosProveedores.Add(FilaACampoPersonalizado(fila));
            foreach (var item in camposPersonalizadosProveedores)
                if (!proveedoresCamposPersonalizadosProveedores.Exists(x => x.Entidad.Id == item.Id))
                    proveedoresCamposPersonalizadosProveedores.Add(new ProveedorCampoPersonalizadoProveedor()
                    {
                        Entidad = item,
                        Valor = String.Empty
                    });
            return proveedoresCamposPersonalizadosProveedores;
        }

        private DomicilioProveedor FilaADomicilio(DataRow fila)
        {
            var domicilio = new DomicilioProveedor();
            domicilio.Id = (Int32)fila["IdDomicilioProveedor"];
            domicilio.Calle = (String)fila["Calle"];
            domicilio.Numero = (String)fila["Numero"];
            domicilio.Piso = (String)fila["Piso"];
            domicilio.Departamento = (String)fila["Departamento"];
            domicilio.Tipo = repositorioTiposDomicilios.DevolverPorId((Byte)fila["IdTipoDomicilio"]);
            domicilio.Barrio = repositorioBarrios.DevolverPorId((Int32)fila["IdBarrio"]);
            return domicilio;
        }

        private TelefonoProveedor FilaATelefono(DataRow fila)
        {
            var telefono = new TelefonoProveedor();
            telefono.Id = (Int32)fila["IdTelefonoProveedor"];
            telefono.CodigoArea = (String)fila["CodigoArea"];
            telefono.Numero = (String)fila["Numero"];
            telefono.Tipo = repositorioTiposTelefonos.DevolverPorId((Byte)fila["IdTipoTelefono"]);
            return telefono;
        }

        private ProveedorCampoPersonalizadoProveedor FilaACampoPersonalizado(DataRow fila)
        {
            var campoPersonalizado = new ProveedorCampoPersonalizadoProveedor();
            campoPersonalizado.Valor = (String)fila["Valor"];
            campoPersonalizado.Entidad = repositorioCamposPersonalizadosProveedores.DevolverPorId((Int32)fila["IdPersonalizadoArticulo"]);
            return campoPersonalizado;
        }

        public void Insertar(Proveedor proveedor)
        {
            proveedor.Id = servicioDatos.Proveedores_Insertar(proveedor.Rubro.Id, proveedor.TipoIva.Id, proveedor.ListaPrecioCompra.Id, proveedor.Codigo, proveedor.Nombre, proveedor.LimiteDeuda, proveedor.Cuit, proveedor.Email, proveedor.SitioWeb, proveedor.Observaciones, proveedor.Imagen);
        }

        public void Modificar(Proveedor proveedor)
        {
            servicioDatos.Proveedores_Modificar(proveedor.Id, proveedor.Rubro.Id, proveedor.TipoIva.Id, proveedor.ListaPrecioCompra.Id, proveedor.Codigo, proveedor.Nombre, proveedor.LimiteDeuda, proveedor.Cuit, proveedor.Email, proveedor.SitioWeb, proveedor.Observaciones, proveedor.Imagen, proveedor.EstaEliminado);
        }

        public void InsertarDomicilio(Proveedor proveedor, DomicilioProveedor domicilio)
        {
            domicilio.Id = servicioDatos.DomiciliosProveedores_Insertar(proveedor.Id, domicilio.Tipo.Id, domicilio.Barrio.Id, domicilio.Calle, domicilio.Numero, domicilio.Piso, domicilio.Departamento);
        }

        public void EliminarDomiciliosPorProveedor(Proveedor proveedor)
        {
            servicioDatos.DomiciliosProveedores_EliminarPorProveedor(proveedor.Id);
        }

        public void InsertarTelefono(Proveedor proveedor, TelefonoProveedor telefono)
        {
            telefono.Id = servicioDatos.TelefonosProveedores_Insertar(proveedor.Id, telefono.Tipo.Id, telefono.CodigoArea, telefono.Numero);
        }

        public void EliminarTelefonosPorProveedor(Proveedor proveedor)
        {
            servicioDatos.TelefonosProveedores_EliminarPorProveedor(proveedor.Id);
        }

        public void EliminarTiposFormasPagosPorProveedor(Proveedor proveedor)
        {
            servicioDatos.ProveedoresTiposFormasPagos_EliminarPorProveedor(proveedor.Id);
        }

        public void InsertarTipoFormaPago(Proveedor proveedor, TipoFormaPago tipoFormaPago)
        {
            servicioDatos.ProveedoresTiposFormasPagos_Insertar(proveedor.Id, tipoFormaPago.Id);
        }

        public void EliminarCamposPersonalizadosPorProveedor(Proveedor proveedor)
        {
            servicioDatos.ProveedoresCamposPersonalizadosProveedores_EliminarPorProveedor(proveedor.Id);
        }

        public void InsertarCampoPersonalizado(Proveedor proveedor, ProveedorCampoPersonalizadoProveedor campoPersonalizado)
        {
            servicioDatos.ProveedoresCamposPersonalizadosProveedores_Insertar(proveedor.Id, campoPersonalizado.Entidad.Id, campoPersonalizado.Valor);
        }

        protected override Proveedor FilaAEntidad(DataRow fila)
        {
            var proveedor = new Proveedor();
            proveedor.Id = (Int32)fila["IdProveedor"];
            proveedor.Codigo = (String)fila["Codigo"];
            proveedor.Nombre = (String)fila["Nombre"];
            proveedor.LimiteDeuda = (Decimal)fila["LimiteDeuda"];
            proveedor.Cuit = (String)fila["Cuit"];
            proveedor.Email = (String)fila["Email"];
            proveedor.SitioWeb = (String)fila["SitioWeb"];
            proveedor.Observaciones = (String)fila["Observaciones"];
            if (fila["Imagen"] != DBNull.Value)
                proveedor.Imagen = (Byte[])fila["Imagen"];
            proveedor.EstaEliminado = (Boolean)fila["EstaEliminado"];
            proveedor.TipoIva = repositorioTiposIvas.DevolverPorId((Byte)fila["IdTipoIva"]);
            proveedor.Rubro = repositorioRubrosProveedores.DevolverPorId((Int32)fila["IdRubroProveedor"]);
            proveedor.ListaPrecioCompra = repositorioListasPreciosCompras.DevolverPorId((Int32)fila["IdListaPrecioCompra"]);
            return proveedor;
        }

        public void EliminarCamposPersonalizadosPorCampoPersonalizado(CampoPersonalizadoProveedor campoPersonalizadoProveedor)
        {
            servicioDatos.ProveedoresCamposPersonalizadosProveedores_EliminarPorCampoPersonalizadoProveedor(campoPersonalizadoProveedor.Id);
        }

        public void ModificarBarrioEnDomicilios(Barrio barrioNuevo, Barrio barrioViejo)
        {
            servicioDatos.DomiciliosProveedores_ModificarBarrio(barrioNuevo.Id, barrioViejo.Id);
        }

        public void ModificarRubroProveedor(RubroProveedor rubroNuevo, RubroProveedor rubroViejo)
        {
            servicioDatos.Proveedores_ModificarRubroProveedor(rubroNuevo.Id, rubroViejo.Id);
        }

        #endregion
    }
}
